<!-- 融合ElForm 和 ElDescriptions，按条件显示ElForm形式还是ElDescriptions形式 -->
<script lang="ts" setup>
import type {
	descriptionProps,
	FormInstance,
	FormItemProps,
	formItemProps,
	FormItemRule,
	FormProps,
} from "element-plus";
import type { ExtractPropTypes } from "vue";
import { mergeProps } from "vue";

import type { BasicOrComponentOpt } from "../basic-or-component/basic-or-component.vue";
import { color } from "echarts";

export type DescriptionItemProps = ExtractPropTypes<typeof formItemProps>;
export type DescriptionProps = Partial<
	ExtractPropTypes<typeof descriptionProps>
>;

export interface FormDescChild {
	hidden?: () => boolean;
	label?: BasicOrComponentOpt;
	prop?: string;
	rule?: FormItemRule[];
	span?: number;
	formItemProps?: FormItemProps;
	formItemClass?: any;
	fontSize?: string;
	fontWeight?: number;
	formItem?: BasicOrComponentOpt;
	descItemProps?: DescriptionItemProps;
	descItemClass?: any;
	descItem?: BasicOrComponentOpt;
}

export interface FormDescProps {
	type: "form" | "desc";
	model?: any;
	column?: number;
	formProps?: Partial<FormProps>;
	formClass?: any;
	descProps?: Partial<DescriptionProps>;
	descClass?: any;
	children: FormDescChild[];
}

const props = withDefaults(defineProps<FormDescProps>(), {
	column: 2,
});
defineOptions({ name: "FormDesc", inheritAttrs: false });

const rules = computed(() => {
	return props.children?.reduce((rules, next) => {
		next.prop && (rules[next.prop] = next.rule);
		return rules;
	}, {} as any);
});

const formRef = shallowRef<FormInstance>();

defineExpose({
	formRef,
});
</script>

<template>
	<el-form
		v-if="type === 'form'"
		ref="formRef"
		:model="model"
		:rules="rules"
		:label-position="formProps?.labelPosition ?? 'top'"
		class="grid-cols-2 grid!"
		:style="{
			'grid-template-columns': `repeat(${column}, 1fr)`,
		}"
		:class="formClass"
		v-bind="mergeProps($attrs, formProps ?? {})"
	>
		<template v-for="item in children" :key="item.prop">
			<el-form-item
				v-if="!item.hidden?.()"
				:prop="item.prop"
				:style="{
					'grid-column': `span ${item.span ?? 2} / span ${item.span ?? 2}`,
				}"
				:class="item.formItemClass"
			>
				<template #label>
					<BasicOrComponent :is="item.label" />
				</template>
				<component
					:is="item.formItem"
					:style="
						item.fontSize && item.fontWeight
							? { fontSize: item.fontSize, fontWeight: item.fontWeight }
							: {}
					"
					v-bind="item.formItemProps"
				/>
			</el-form-item>
		</template>
	</el-form>
	<el-descriptions
		v-if="type === 'desc'"
		:direction="descProps?.direction ?? 'vertical'"
		:column="column"
		:label-align="true"
		:class="descClass"
		v-bind="mergeProps($attrs, descProps ?? {})"
		class="form-desc--descriptions"
	>
		<template v-for="item in children" :key="item.prop">
			<el-descriptions-item
				v-if="!item.hidden?.()"
				:class="item.descItemProps"
				:span="item.span ?? 2"
				label-align="right"
				v-bind="item.descItemProps"
			>
				<BasicOrComponent
					:is="item.fontSize ? item.label : item.label + '：'"
					style="text-align: right"
				/>
				<div
					v-if="item.fontSize && item.fontWeight"
					:style="
						item.fontSize && item.fontWeight
							? { fontSize: item.fontSize, fontWeight: item.fontWeight }
							: {}
					"
				>
					{{ item.descItem }}
				</div>
				<component v-else :is="item.descItem" />
			</el-descriptions-item>
		</template>
	</el-descriptions>
</template>

<style lang="scss">
.form-desc--descriptions {
	.el-descriptions__table {
		table-layout: fixed;
	}

	.el-descriptions__cell.el-descriptions__content.is-vertical-content {
		height: 36px;
    // color: aqua;
	}
}
</style>
